﻿using System.Threading;
using System.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using Microsoft.DirectX.DirectSound;




namespace SpeechToText.STT
{
    public delegate void RecordIsDoneMethod(WavResource wav_resource);

    public class Microphone: IDisposable
    {
        #region Private Values

        private SoundCapture sc;
  
        #endregion

        public event RecordIsDoneMethod AsyncRecordDone;



        #region Public Values

        public WaveFormat Format { get; private set; }

        public bool isRecording { get; private set; }

        public Control Owner { get; set; }

        #endregion




        #region Constructors and Destructors

        public Microphone(Control Owner)
        {
            this.Owner = Owner;
            isRecording = false;
            Format = WavHeader.CreateWaveFormat(32000, 16, 1);
            sc = new SoundCapture(Format);
        }

        ~Microphone()
        {
            Dispose();
        }

        #endregion
        



        #region Publuc Methods

        public void Dispose()
        {
            if (sc != null) sc.Dispose();
            sc = null;
        }

        public void Stop()
        {
            if (!isRecording) return;
            isRecording = false;
            sc.Stop();
        }

        public void Start()
        {
            if (isRecording) return;
            isRecording = true;
            sc.Start();
        }

        /// <summary>
        /// Очищает буфер микрофона от записанного ранее звука
        /// </summary>
        public void ClearMicBufer()
        {
            sc.ClearRecord();
        }
        
        /// <summary>
        /// Вернет готовый wav файл
        /// </summary>
        /// <returns></returns>
        public WavResource GetRecord()
        {
            return sc.CreateWavResource();
        }

        /// <summary>
        /// Поток байт записаный микрофоном
        /// </summary>
        /// <returns></returns>
        public byte[] GetMicrophoneData()
        {
            return sc.GetSoundDataArray();
        }

        /// <summary>
        /// Запись в течение заданного количества милисекунд 
        /// </summary>
        /// <param name="Milisec"></param>
        /// <returns></returns>
        public WavResource RecordFor(int Milisec)
        {
            Start();
            Thread.Sleep(Milisec);
            Stop();

            return GetRecord();
        }

        /// <summary>
        ///  Асинхронная запись.
        /// </summary>
        /// <param name="Milisec">Время</param>
        /// <param name="CallMethod">Метод, вызываемый, когда запись завершена</param>
        public void AsyncRecordFor(int Milisec)
        {
            (new Thread(delegate() 
                {
                    Start();

                    while (Milisec != 0)
                    {
                        if (sc == null) return;

                        if (Milisec > 50)
                        {
                            Thread.Sleep(50);
                            Milisec -= 50;
                        }
                        else
                        {
                            Thread.Sleep(Milisec);
                            Milisec = 0;
                        }
                    }

                    Stop();

                    if (AsyncRecordDone != null) Owner.Invoke(AsyncRecordDone, new object[] { GetRecord() });
            
            })).Start();
        }

        /// <summary>
        /// запишет звук, как только он появится
        /// </summary>
        /// <param name="SoundVolume">уровень громкости звука. вещественное значение от 0 до 1, при превышении начнется запись. Рекомендуется 0.15</param>
        /// <param name="SilenceMilisec">если после всплеска шума тишина продлится SilenceMilisec запись завершится </param>
        /// <returns></returns>
        
        #endregion
    }
}
